------------------------------------------------
--Icetip
--描述: wow提示增强插件.
--作者: 月色狼影
--$Rev: 1888 $
--$Id: core.lua 1159 2008-04-27 10:18:53Z wolftankk $
------------------------------------------------
--[[
需求:
1. 改变名字颜色
2. 声望, 目标
3. 等级差距 以及职业颜色着色
4. 背景颜色的改变.
]]
local Icetip = CreateFrame("Frame");
Icetip = LibStub("AceHook-3.0"):Embed(Icetip)
Icetip = LibStub("AceTimer-3.0"):Embed(Icetip)
_G.Icetip = Icetip
Icetip.vesion = 3.06
Icetip.revision = tonumber(("$Revision: 1888 $"):match("%d+"));
local L = LibStub("AceLocale-3.0"):GetLocale("Icetip")

local SM = LibStub("LibSharedMedia-3.0")

local tooltips = {
	GameTooltip,
	ItemRefTooltip,
	ShoppingTooltip1,
	ShoppingTooltip2,
	ShoppingTooltip3,
}
--db
local options
function Icetip:GetDefaultConfig()
	if not options then
		options = {
			--main func
			scale = 1,
			bgColor = {
				guild = {0, 0.15, 0, 1},
				faction = {0.25, 0.25, 0, 1},
				hostilePC = {0.25, 0, 0, 1},
				hostileNPC = {0.15, 0, 0, 1},
				neutralNPC = {0.15, 0.15, 0, 1},
				friendlyPC = {0, 0, 0.25, 1},
				friendlyNPC = {0, 0, 0.15, 1},
				other = {0, 0, 0, 1},
				dead = {0.15, 0.15, 0.15, 1},
				tapped = {0.25, 0.25, 0.25, 1},
			},
			--默认
			border_color = {
				r = 1,
				g = 1,
				b = 1,
				a = 1,
			},
			--style
			tooltipStyle = {
				bgTexture = "Blizzard Tooltip",
				borderTexture = "Blizzard Tooltip",
				tile = false,
				tileSize = 8,
				EdgeSize = 16,
				customColor = true,
			},
			itemQBorder = true,--物品材质框
			--鼠标提示位置设定
			setAnchor = {
				unitAnchor = "CURSOR_BOTTOM",
				unitOffsetX = 0,
				unitOffsetY = 0,
				frameAnchor = "BOTTOMRIGHT",
				frameOffsetX = -93,
				frameOffsetY = 110,
			},
			--渐隐
			tooltipFade = {
				units = "hide",
				objects ="fade",
				unitFrames = "fade",
				otherFrames = "hide",
			},
			--healthbar
			healthbar = {
				texture = "Blizzard",
				size = 5,
				position = "BOTTOM",
				enable = true,
			},
			powerbar = {
				texture = "Blizzard",
				size = 5,
				position = "BOTTOM",
				enable = true,
			},
			--mouse
			mousetarget = {
				showTalent = true,
				showTarget = true,
				showFaction = true,
				showServer = true,
				SGuildColor = {
					r = 0.9,
					g = 0.45,
					b = 0.7,
				},
				DGuildColor = {
					r = 0.8,
					g = 0.8,
					b = 0.8,
				}
			},
			--raid target
			raidtarget = {
				enable = false,
				position = "TOP",
				size = 20,
			},
		}
	end
	return options
end

local function ItemQualityBorder()
	for i=1, #tooltips do
		local item = select(2, tooltips[i]:GetItem());
		if item then
			local quality = select(3, GetItemInfo(item));
			if quality then
				local r, g, b = GetItemQualityColor(quality);
				tooltips[i]:SetBackdropBorderColor(r, g, b);
			end
		end
	end
end

function Icetip:OnInitialize(event, addon)
	if event == "ADDON_LOADED" and addon == "Icetip" then
		if IcetipDB == nil or not next(IcetipDB) or not IcetipDB.vesion then
			IcetipDB = self:GetDefaultConfig()
			IcetipDB.vesion = tonumber(Icetip.vesion);
		end
		if tonumber(IcetipDB.vesion) < tonumber(Icetip.vesion) then
			IcetipDB = self:GetDefaultConfig()
			IcetipDB.vesion = tonumber(Icetip.vesion);
		end
		--IcetipDB = self:GetDefaultConfig()
		self.db = IcetipDB
	elseif event == "PLAYER_LOGIN" then
		self.OnEnable()
	elseif event == "CURSOR_UPDATE" then
		self.CURSOR_UPDATE();
	end
end

function Icetip:OnEnable()
	--hook
	hooksecurefunc("GameTooltip_SetDefaultAnchor", function(tooltip, parent) Icetip:SetTooltipAnchor(tooltip, parent) end);
	Icetip:RawHook(GameTooltip, "FadeOut", "GameTooltip_FadeOut", true);
	Icetip:RawHook(GameTooltip, "Hide", "GameTooltip_Hide", true);
	Icetip:HookScript(GameTooltip, "OnShow", "GameTooltip_OnShow");
	Icetip:HookScript(GameTooltip, "OnHide", "GameTooltip_OnHide");
	Icetip:HookScript(GameTooltip, "OnTooltipSetUnit", "GameTooltip_SetUnit");
	--Icetip:HookScript(GameTooltip, "OnTooltipSetItem", "GameTooltip_SetItem")

	local previousDead = false
	Icetip:ScheduleRepeatingTimer(function() 
		local mouse_unit = Icetip:GetMouseoverUnit()
		if UnitExists(mouse_unit) then
			if UnitIsDeadOrGhost(mouse_unit) then
				if previousDead == false then
					GameTooltip:Hide()
					GameTooltip_SetDefaultAnchor(GameTooltip, UIParent);
					GameTooltip:SetUnit(mouse_unit)
					GameTooltip:Show()
				end
				previousDead = true
			else
				previousDead = false
			end
		else
			previousDead = nil
		end
	end, 0.05)
	Icetip:RegisterEvent("CURSOR_UPDATE")
end

local forgetNextOnTooltipMethod = false

--update db
function Icetip:PorfileChanged(db)
	
end

local currentOffsetX, currentOffsetY = 0, 0
local currentCursorAnchor = "BOTTOM"
local currentAnchorType = "CURSOR"
local currentOwner = UIParent

local anchorOpposite = {
	BOTTOMLEFT = "TOPLEFT",
	BOTTOM = "TOP",
	BOTTOMRIGHT = "TOPRIGHT",
	LEFT = "RIGHT",
	RIGHT = "LEFT",
	TOPLEFT = "BOTTOMLEFT",
	TOP = "BOTTOM",
	TOPRIGHT = "BOTTOMRIGHT",
}

local function ReanchorTooltip()
	GameTooltip:ClearAllPoints();
	local scale = GameTooltip:GetEffectiveScale();
	if currentAnchorType == "PARENT" then
		GameTooltip:SetPoint(currentCursorAnchor, currentOwner, anchorOpposite[currentCursorAnchor], currentOffsetX, currentOffsetY)
	elseif currentAnchorType == "CURSOR" then
		local x, y = GetCursorPosition();
		x, y = x/scale + currentOffsetX, y/scale +currentOffsetY;
		GameTooltip:SetPoint(currentCursorAnchor, UIParent, "BOTTOMLEFT", x, y);
	end
end

function Icetip:SetTooltipAnchor(tooltip, parent, ...)
	local db = self.db["setAnchor"]
	
	local anchor, offsetX, offsetY
	currentOwner = parent
	if parent == UIParent then --角色
		anchor = db.unitAnchor
		offsetX = db.unitOffsetX
		offsetY = db.unitOffsetY
	else --frame
		anchor = db.frameAnchor
		offsetX = db.frameOffsetX
		offsetY = db.frameOffsetY
	end
	if anchor:find("^CURSOR") or anchor:find("^PARENT") then
		if anchor == "CURSOR_TOP" and math.abs(offsetX) < 1 and math.abs(offsetY) < 0 then
			tooltip:SetOwner(parent, "ANCHOR_CURSOR");
		else
			currentOffsetX = offsetX
			currentOffsetY = offsetY
			currentCursorAnchor = anchor:sub(8);
			currentAnchorType = anchor:sub(1, 6);
			ReanchorTooltip()
		end
	else
		tooltip:SetOwner(parent, "ANCHOR_NONE");
		tooltip:ClearAllPoints();
		tooltip:SetPoint(anchor, UIParent, anchor, offsetX, offsetY)
	end
end

function Icetip:GameTooltip_FadeOut(tooltip, ...)
	self.hooks[tooltip].FadeOut(tooltip, ...)
	local kind
	local db = self.db["tooltipFade"];
	
	if GameTooltip:GetUnit() then
		if GameTooltip:IsOwned(UIParent) then
			kind = db.units
		else
			kind = db.unitFrames
		end
	else
		if GameTooltip:IsOwned(UIParent) then
			kind = db.objects
		else
			kind = db.otherFrames
		end
	end
	
	if kind == "fade" then
		self.hooks[tooltip].FadeOut(tooltip, ...)
	else
		GameTooltip:Hide()
	end
end

function Icetip:GameTooltip_Hide(tooltip, ...)
	local db = self.db["tooltipFade"]
	if tooltip.justHide then
		return self.hooks[tooltip].Hide(tooltip, ...)
	end
	local kind
	if GameTooltip:GetUnit() then
		if GameTooltip:IsOwned(UIParent) then
			kind = db.units
		else
			kind = db.unitFrames
		end
	else
		if GameTooltip:IsOwned(UIParent) then
			kind = db.objects
		else
			kind = db.otherFrames
		end
	end
	
	if kind == "fade" then
		return GameTooltip:FadeOut()
	else
		return self.hooks[tooltip].Hide(tooltip, ...)
	end
end

function Icetip:GameTooltip_OnShow(tooltip, ...)
	
	Icetip.Appstyle:Tooltip_OnShow(tooltip, ...)
	if IcetipDB.itemQBorder and tooltip:GetItem() then
		ItemQualityBorder()
	else
		tooltip:SetBackdropBorderColor(IcetipDB["border_color"].r, IcetipDB["border_color"].g, IcetipDB["border_color"].b, IcetipDB["border_color"].a);
	end

	if tooltip:GetUnit() then
		self:PreTooltipSetUnit()
		forgetNextOnTooltipMethod = true
		Icetip.HealthBar.OnTooltipShow();
		Icetip.PowerBar.OnTooltipShow();
		Icetip.MouseTarget.OnTooltipShow()
		Icetip.RaidTarget.OnTooltipShow();
	elseif tooltip:GetItem() then
		forgetNextOnTooltipMethod = true
	elseif tooltip:GetSpell() then

	end
	if IcetipDB["tooltipStyle"].customColor then
		self:SetBackgroundColor()
	end
	self:SetTooltipScale(nil, IcetipDB.scale)

	self.hooks[tooltip].OnShow(tooltip, ...)
	self:OnTooltipShow();
end

function Icetip:GameTooltip_OnHide(tooltip, ...)
	self:OnTooltipHide()
	Icetip.HealthBar.OnTooltipHide()
	Icetip.PowerBar.OnTooltipHide()
	Icetip.RaidTarget.OnTooltipHide();
	forgetNextOnTooltipMethod = false
	if self.hooks[tooltip] and self.hooks[tooltip].OnHide then
		self.hooks[tooltip].OnHide(tooltip, ...)
	end
end

function Icetip:GameTooltip_SetUnit(tooltip, ...)
	--self.hooks[tooltip].OnTooltipSetUnit(tooltip, ...);
	if forgetNextOnTooltipMethod then
		forgetNextOnTooltipMethod = false
	else
		Icetip.HealthBar.SetUnitHealthBar()
		Icetip.PowerBar.SetUnitPowerBar()
		Icetip.MouseTarget.SetUnitTarget()
		self:OnTooltipSetUnit()
	end
end

function Icetip:GameTooltip_SetItem(tooltip, ...)
	forgetNextOnTooltipMethod = true
	--self.hooks[tooltip].OnTooltipSetItem(tooltip, ...);
	if forgetNextOnTooltipMethod then
		forgetNextOnTooltipMethod = false
	end
end

local currentSameFaction = false
function Icetip:PreTooltipSetUnit()
	local myWatchedFaction = GetWatchedFactionInfo();
	currentSameFaction = false
	if myWatchedFaction then
		for i = 1, 10 do
			local left = _G["GameTooltipTextLeft"..i]
			if left then
				if left:GetText() == myWatchedFaction then
					currentSameFaction = true
					break
				end
			end
		end
	end
end

function Icetip:SetBackgroundColor(given_kind, r, g,b,a, tooltip)
	if not tooltip then
		tooltip = GameTooltip
	end
	local kind = given_kind
	if not kind then
		kind = "other"
		local unit
		if (type(tooltip.GetUnit) == "function") then
			_, unit = tooltip:GetUnit()
		end

		if unit and UnitExists(unit) then
			if UnitIsDeadOrGhost(unit) then
				kind = "dead"
			elseif UnitIsTapped(unit) and not UnitIsTappedByPlayer(unit) then
				kind = "tapped"
			elseif tooltip == GameTooltip and currentSameFaction then--声望
				kind = "faction"
			elseif UnitIsPlayer(unit) then
				if UnitIsFriend("player", unit) then
					local playerGuild = GetGuildInfo("player");
					if playerGuild and playerGuild == GetGuildInfo(unit) or UnitIsUnit("player", unit) then
						kind = "guild"
					else
						local friend = false
						local name = UnitName(unit);
						for i =1, GetNumFriends() do
							if GetFriendInfo(i) == name then
								friend = true
								break
							end
						end
						if friend then
							kind = "guild"
						else
							kind = "friendlyPC"
						end
					end
				else
					kind = "hostilePC"
				end
			else
				if (UnitIsFriend("player", unit)) then
					kind = "friendlyNPC"
				else
					local reaction = UnitReaction(unit, "player")
					if not reaction or reaction <=2 then
						kind = "hostileNPC"
					else
						kind = "neutralNPC"
					end
				end
			end
		end
	end

	local bgColor = self.db.bgColor[kind]
	if r then
		bgColor[1] = r
		bgColor[2] = g
		bgColor[3] = b
		bgColor[4] = a
	else
		r, g, b, a = unpack(bgColor);
	end

	if given_kind then
		self:SetBackgroundColor(nil, nil, nil, nil, nil, tooltip)
		return
	end

	tooltip:SetBackdropColor(r, g, b, a)
end

function Icetip:SetTooltipScale(tooltip, value)
	if not tooltip then
		tooltip = GameTooltip
	end
	
	tooltip:SetScale(value)
end

function Icetip:GetMouseoverUnit()
	local _, tooltipUnit = GameTooltip:GetUnit()
	if not tooltipUnit or not UnitExists(tooltipUnit) or UnitIsUnit(tooltipUnit, "mouseover") then
		return "mouseover"
	else
		return tooltipUnit
	end
end

local lastMouseoverUnit
local function checkUnitExistance()
	local mouseover_unit = Icetip:GetMouseoverUnit()
	if not GameTooltip:GetUnit() or not UnitExists(mouseover_unit) or (lastMouseoverUnit == "mouseover" and mouseover_unit ~= "mouseover") then
		Icetip:CancelTimer(Icetip_Fade_checkUnitExistance, true)
		local kind
		local db = Icetip.db["tooltipFade"]
		if GameTooltip:IsOwned(UIParent) then
			kind = db.units
		else
			kind = db.unitFrames
		end
		if kind == "fade" then
			GameTooltip:FadeOut()
		else
			GameTooltip:Hide()
		end
	end
end

local function checkAlphaFrame()
	if GameTooltip:GetAlpha() < 1 then
		Icetip:CancelTimer(Icetip_Fade_checkUnitExistance, true)
		local kind
		local db = IcetipDB["tooltipFade"]
		if GameTooltip:IsOwned(UIParent) then
			kind = db.objects
		else
			kind = db.otherFrames
		end

		if kind == "fade" then
			GameTooltip:FadeOut()
		else
			GameTooltip:Hide()
		end
	end
end

local cursorChangedWithTooltip = false
function Icetip:OnTooltipShow()
	self:CancelTimer(Icetip_Fade_runHide, true)
	if GameTooltip:GetUnit() then
		Icetip_Fade_checkUnitExistance = self:ScheduleRepeatingTimer(checkUnitExistance, 0)
	else
		if GameTooltip:IsOwned(UIParent) then
			cursorChangedWithTooltip = true
		end
		Icetip_Fade_checkUnitExistance = self:ScheduleRepeatingTimer(checkAlphaFrame, 0)
	end
end

function Icetip:OnTooltipHide()
		--kill
	cursorChangedWithTooltip = false
	self:CancelTimer(Icetip_Fade_checkUnitExistance, true)
end

function Icetip:OnTooltipSetUnit()
	lastMouseoverUnit = Icetip:GetMouseoverUnit()
end

local function runHide()
	local db = IcetipDB["tooltipFade"]
	if db.objects == "fade" then
		GameTooltip:FadeOut()
	else
		GameTooltip:Hide()
	end
end

local function donothing() end

function Icetip:CURSOR_UPDATE(...)
	if cursorChangedWithTooltip then
		Icetip_Fade_runHide = Icetip:ScheduleTimer(runHide, 0)
	else
		Icetip_Fade_doNothing = Icetip:ScheduleTimer(donothing, 0)
	end
end

--method
Icetip:RegisterEvent("ADDON_LOADED")
Icetip:RegisterEvent("PLAYER_LOGIN")
Icetip:SetScript("OnEvent", Icetip.OnInitialize)